package com.winning.core.net;

import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.Map;

import javax.xml.namespace.QName;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.cxf.Bus;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;

import com.cownew.ctk.common.StringUtils;
import com.framework.util.date.DateConvert;
import com.winning.common.Constans;
import com.winning.common.beans.ihe.IHERequestBodyBean;
import com.winning.common.beans.xmlTemp.XMLTempConfigBean;
import com.winning.common.data.service.PlatBasicDataService;
import com.winning.common.tools.XMLTool;
import com.winning.core.base.IHEResponseServiceInter;

/**
 * 类名称：CXFWebserviceClentTool
 * 类描述：CXF客户端调用
 * 创建人：liuwensheng
 * 创建时间：2016-12-14 上午10:57:15
 * 修改人：liuwensheng
 * 修改时间：2016-12-14 上午10:57:15
 * 修改备注：
 */
public class CXFWebserviceClent {
    private static Logger LOGGER = Logger.getLogger(Constans.LOG4J_PBS_LOGGER_ID);


    private static final String JBXX_WS_NAME = "JBXXSCFW";

    private static final String AUDIT_WS_NAME = "AUDITSCFW";


    /**
     * cxf客户端发送webservice请求 <br/>
     * 方法名称: sendCXFWebserviceRequestHandler
     *
     * @param platBasicDataService 平台基础服务对象
     * @param iheRequestBodyBean   模板对象
     * @param paramObj             参数
     * @return Object[]  返回类型说明<br/>
     * @throws <br/>
     * @author liuwensheng@winning.com.cn<br/>
     * 创建时间：2016-12-10/下午12:41:32<br/>
     */
    public static Object[] sendCXFWebserviceRequestHandler(Document documentSource, PlatBasicDataService platBasicDataService, IHERequestBodyBean iheRequestBodyBean, String requestXMLValue, Map<String, Object> requestInfoMap, XMLTempConfigBean xmlTempConfigBean) {
        //wsdl服务路径地址
        String wsdlURL = iheRequestBodyBean.getWebserviceURL();

        //平台webservice接口服务名称
        String actionMethodName = iheRequestBodyBean.getActionMethodName();

        //webservice开发的接口方法名称
        String webserviceMethodName = iheRequestBodyBean.getWebserviceMethodName();

        //IHE请求响应结果处理器
        String iheResponseClass = iheRequestBodyBean.getResponseClass();

        Object[] result = null;

        String tokenHeader = "weining@YZ-WN-JCHIS/123456";

        String responseXMLMessage = "";

        //审计消息标准XML结构
        Document autidDocument = null;

        autidDocument = XMLTool.getDocumentFromXMLString(requestXMLValue, true);


        //不依赖服务器端接口来完成调用的，也就是不仅仅能调用Java的接口
        JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();
        Client client = null;
        client = clientFactory.createClient(wsdlURL);
        try {
            //服务名称固定，参数可变
            if (actionMethodName.equals("audit")) {
                //审计接口服务
                result = client.invoke(webserviceMethodName, requestXMLValue);
            } else {
                result = client.invoke(webserviceMethodName, actionMethodName, requestXMLValue, tokenHeader);
            }


            //关闭连接
            client.destroy();

            if (result != null && result.length > 0) {
                responseXMLMessage = (String) result[0];

                LOGGER.info("--> cxf客户端调用返回结果:" + result[0]);
            } else {
                LOGGER.info("--> cxf客户端调用返回结果为null");
            }

            //调用具体的处理接口处理IHE消息响应结果
            Map<String, Object> responseMap = responseMessageHandler(platBasicDataService, iheResponseClass, responseXMLMessage, requestInfoMap, xmlTempConfigBean.getDbDataSourseID());


            //****************************************** 增加审计接口流程 *********************************************************
//			if(iheRequestBodyBean != null && iheRequestBodyBean.isAudit() && responseMap != null)
//			{
//								
//				if(responseMap.containsKey("RESPONSE_RESULT"))
//				{
//					String responseResultValue = (String)responseMap.get("RESPONSE_RESULT");
//					
//					if("AA".equals(responseResultValue))
//					{
//						//调用审计接口
//						sendCDAAuditService(autidDocument, iheRequestBodyBean, "0");
//					}
//					else
//					{
//						//调用审计接口
//						sendCDAAuditService(autidDocument, iheRequestBodyBean, "4");
//					}
//				}
//			}
        } catch (Exception e) {
            //打印异常堆栈信息
            LOGGER.error(e, e.fillInStackTrace());
            e.printStackTrace();

//			//如果共享文档注册异常，也需要调用审计接口，向平台发送共享文档注册异常消息
//			if(iheRequestBodyBean != null && iheRequestBodyBean.isAudit())
//			{
//				//调用审计接口
//				sendCDAAuditService(autidDocument, iheRequestBodyBean, "12");
//			}

        }


        return result;
    }


    /**
     * 方法名称: sendAxisFWebserviceRequestHandler 发送Axis请求
     *
     * @param
     * @return Object[]
     * @throws
     * @author zhaqiang@winning.com.cn
     * 创建时间：2018-1-11/上午10:39:49
     */
    public static Object[] sendAxisFWebserviceRequestHandler(Document documentSource, PlatBasicDataService platBasicDataService, IHERequestBodyBean iheRequestBodyBean, String requestXMLValue, Map<String, Object> requestInfoMap, XMLTempConfigBean xmlTempConfigBean) {


        String result = null;
        try {

            //wsdl服务路径地址
            String wsdlURL = iheRequestBodyBean.getWebserviceURL();

            //平台webservice接口服务名称
            String actionMethodName = iheRequestBodyBean.getActionMethodName();

            //webservice开发的接口方法名称
            String webserviceMethodName = iheRequestBodyBean.getWebserviceMethodName();

            //IHE请求响应结果处理器
            String iheResponseClass = iheRequestBodyBean.getResponseClass();

            String responseXMLMessage = "";

            //审计消息标准XML结构
            //Document autidDocument = null;

            //autidDocument = XMLTool.getDocumentFromXMLString(requestXMLValue, true);

            String url = wsdlURL.replace("?wsdl", "");
            Service service = new Service();
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);
            call.setUseSOAPAction(true);
            call.setSOAPActionURI("");
            QName QNAME = new QName("urn:hl7-org:v3", webserviceMethodName);
            call.setOperationName(QNAME);

            call.addParameter(new QName("action"),
                    org.apache.axis.encoding.XMLType.XSD_STRING,
                    javax.xml.rpc.ParameterMode.IN);
            call.addParameter(new QName("message"),
                    org.apache.axis.encoding.XMLType.XSD_STRING,
                    javax.xml.rpc.ParameterMode.IN);
            call.addParameter(new QName("securityToken"),
                    org.apache.axis.encoding.XMLType.XSD_STRING,
                    javax.xml.rpc.ParameterMode.IN);
            call.addParameter(new QName("return"),
                    org.apache.axis.encoding.XMLType.XSD_STRING,
                    javax.xml.rpc.ParameterMode.OUT);


            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);
            result = (String) call.invoke(new Object[]{actionMethodName, requestXMLValue, "weining@YZ-WN-JCHIS/123456"});


            if (!StringUtils.isEmpty(result)) {
                responseXMLMessage = result;

                LOGGER.info("--> cxf客户端调用返回结果:" + result);
            } else {
                LOGGER.info("--> cxf客户端调用返回结果为null");
            }

            //调用具体的处理接口处理IHE消息响应结果
            Map<String, Object> responseMap = responseMessageHandler(platBasicDataService, iheResponseClass, responseXMLMessage, requestInfoMap, xmlTempConfigBean.getDbDataSourseID());

        } catch (Exception e) {

            LOGGER.error(e, e.fillInStackTrace());
        }

        return new Object[]{result};
    }

    /**
     * 发送共享文档CDA审计服务
     * 方法名称: sendCDAAuditService
     *
     * @param documentSource        hl7标准的消息XML结构
     * @param iheRequestBodyBean    配置模板对象
     * @param eventOutcomeIndicator 共享文档注册请求返回结果
     *                              void  返回类型说明
     * @author liuwensheng@winning.com.cn<br/>
     * 创建时间：2017-1-18/下午1:30:08<br/>
     */
    private static void sendCDAAuditService(Document documentSource, IHERequestBodyBean iheRequestBodyBean, String eventOutcomeIndicator) {
        //审计接口wsdl地址
        String auditWSDLURL = iheRequestBodyBean.getAuditWebserviceURL();


        //患者信息ID
        String patientID = XMLTool.selectElementValueByXPath(documentSource, "xsi:ProvideAndRegisterDocumentSetRequest/xsi:SourcePatientID");
        LOGGER.info("--> 审计接口调用, 区域内患者ID:" + patientID);

        //区域内文档ID
        String documentId = XMLTool.selectAttributeValueByXPath(documentSource, "xsi:ProvideAndRegisterDocumentSetRequest/xsi:RegistryPackage/xsi:SubmissionSet/@targetObject");
        LOGGER.info("--> 审计接口调用, 区域内文档ID:" + documentId);

        //文档唯一ID
        String documentUniqueId = XMLTool.selectElementValueByXPath(documentSource, "xsi:ProvideAndRegisterDocumentSetRequest/xsi:RegistryPackage/xsi:SubmissionSet/xsi:UniqueId");
        LOGGER.info("--> 审计接口调用, 文档唯一ID:" + documentUniqueId);

        //调用审计接口
        sendCDAAuditMessageHandler(auditWSDLURL, eventOutcomeIndicator, documentId, documentUniqueId, patientID);
    }

    /**
     * 发送共享文档审计请求，必须在每次共享文档注册请求处理后，可能是成功或者失败，也可能是在异常处理流程中发起
     * 方法名称: sendCDAAuditMessageHandler
     *
     * @param wsdlURL               审计接口webservice地址 http://59.255.59.31:8280/services/audit?wsdl
     * @param eventOutcomeIndicator 表示事件结果，共享文档注册返回的结果情况,根据情况填写. 0-正常;4-一般错误;8-重要错误;12-严重错误
     * @param documentId            共享文档注册请求xml入参中的文档ID。
     * @param documentUniqueId      共享文档注册请求xml入参中的文档全球唯一标识号
     * @param patientID             共享文档注册请求xml入参患者ID
     *                              void  返回类型说明
     * @author liuwensheng@winning.com.cn<br/>
     * 创建时间：2017-1-17/上午9:27:39<br/>
     */
    public static void sendCDAAuditMessageHandler(String wsdlURL, String eventOutcomeIndicator, String documentId, String documentUniqueId, String patientID) {

        //CXF连接
        Client client = null;

        try {
            LOGGER.info("-->  审计接口开始提交服务");

            //从文件系统中读取配置好的审计接口入参xml内容
            Document audiMessageDoc = XMLTool.getXMLDocument("com/winning/ihe/cda/auditMessage/AuditMessage_xjbt.xml");


            //时间格式化，审计消息样例中的时间代毫秒值0，为了保持一致，格式化增加0
            String eventDateTimeValue = DateConvert.convert(new Date(), "yyyy-MM-dd'T'HH:mm:ss.0");

            //表示事件的发生时间,根据情况填写,2017-01-17T09:44:37.0
            Attribute eventDateTimeAttr = XMLTool.selectAttributeObjectByXPath(audiMessageDoc, "xsi:AuditMessage/xsi:EventIdentification/@EventDateTime");
            if (eventDateTimeAttr != null) {
                eventDateTimeAttr.setValue(eventDateTimeValue);
            }


            //共享文档注册返回的结构，根据情况填写. 0-正常;4-一般错误;8-重要错误;12-严重错误
            Attribute eventOutcomeIndicatorAttr = XMLTool.selectAttributeObjectByXPath(audiMessageDoc, "xsi:AuditMessage/xsi:EventIdentification/@EventOutcomeIndicator");
            if (eventOutcomeIndicatorAttr != null) {
                eventOutcomeIndicatorAttr.setValue(eventOutcomeIndicator);
            }


            //共享文档注册患者ID
            Attribute ParticipantObjectID = XMLTool.selectAttributeObjectByXPath(audiMessageDoc, "xsi:AuditMessage/xsi:ParticipantObjectIdentification[@ParticipantObjectTypeCode='1']/@ParticipantObjectID");
            if (ParticipantObjectID != null) {
                ParticipantObjectID.setValue(patientID);
            }


            //共享文档注册请求xml入参中的文档ID。
            Attribute participantObjectIDAttr = XMLTool.selectAttributeObjectByXPath(audiMessageDoc, "xsi:AuditMessage/xsi:ParticipantObjectIdentification[@ParticipantObjectTypeCode='2']/@ParticipantObjectID");
            if (participantObjectIDAttr != null) {
                participantObjectIDAttr.setValue(documentId);
            }


            //共享文档注册请求xml入参中的文档全球唯一标识号
            Attribute participantObjectIDTypeCodeAttr = XMLTool.selectAttributeObjectByXPath(audiMessageDoc, "xsi:AuditMessage/xsi:ParticipantObjectIdentification[@ParticipantObjectTypeCode='2']/xsi:ParticipantObjectIDTypeCode/@code");
            if (participantObjectIDTypeCodeAttr != null) {
                participantObjectIDTypeCodeAttr.setValue(documentUniqueId);
            }


            LOGGER.info("-->审计接口调用,调用路径：" + wsdlURL);

            //生成请求消息入参
            String audiRequestXMLMessage = audiMessageDoc.asXML();

            LOGGER.info("-->审计接口调用,一条请求审计信息：" + audiRequestXMLMessage);

            Object[] result = null;

            JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();

            client = clientFactory.createClient(wsdlURL);

            //服务名称固定，参数可变
            result = client.invoke("audit", audiRequestXMLMessage);

            //关闭连接
            client.destroy();

            if (result != null && result.length > 0) {
                LOGGER.info("--> 审计消息接口调用返回结果:" + result[0]);
            } else {
                LOGGER.info("--> 审计消息接口调用返回结果为null");
            }
        } catch (Exception e) {
            //打印异常堆栈信息
            LOGGER.error(e, e.fillInStackTrace());
            e.printStackTrace();
        } finally {

        }

    }


    /**
     * 处理响应消息的接口 <br/>
     * 方法名称: responseMessageHandler
     *
     * @param
     * @return void  返回类型说明<br/>
     * @throws <br/>
     * @author liuwensheng@winning.com.cn<br/>
     * 创建时间：2016-12-14/下午1:16:17<br/>
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Object> responseMessageHandler(PlatBasicDataService platBasicDataService, String iheResponseClass, String responseXMLMessage, Map<String, Object> requestInfoMap, String dataSourseID) {
        Map<String, Object> resonseMap = null;

        //调用响应处理器
        Class<IHEResponseServiceInter> responseClass = null;
        try {
            //根据配置的class路径，加载实现类
            responseClass = (Class<IHEResponseServiceInter>) Class.forName(iheResponseClass);

            //实例化具体类，并转型到接口
            IHEResponseServiceInter iheResponseServiceInter = responseClass.newInstance();

            //处理响应消息
            resonseMap = iheResponseServiceInter.resonseHandler(platBasicDataService, responseXMLMessage, requestInfoMap, dataSourseID);
        } catch (ClassNotFoundException e) {
            //打印异常堆栈信息
            LOGGER.error(e, e.fillInStackTrace());
            e.printStackTrace();
        } catch (InstantiationException instantiationException) {
            LOGGER.error(instantiationException, instantiationException.fillInStackTrace());
            instantiationException.printStackTrace();
        } catch (IllegalAccessException e) {
            LOGGER.error(e, e.fillInStackTrace());
            e.printStackTrace();
        }

        return resonseMap;

    }

}
